<!--  
组件使用说明：
1. props: 
   - imgurl: 图片地址（网络或本地）
   - list: 批改数据数组
2. events:
   - @updateList: 当用户手动纠错或删除标注时触发，返回更新后的list数据
   
使用示例：
<canvastest 
  :imgurl="imageUrl" 
  :list="correctList" 
  @updateList="handleListUpdate"
></canvastest>

handleListUpdate(updatedList) {
  this.correctList = updatedList
}
-->
<template>
	<view class="container">
		<canvas canvas-id="myCanvas" id="myCanvas" type="2d" @touchstart="handleTouchStart" @touchmove="handleTouchMove"
			@touchend="handleTouchEnd" :style="canvasStyle"></canvas>

		<!-- 编辑弹出层 -->
		<u-popup v-model="showEditDialog" border-radius="16" mode="center">
			<view style="width: 550rpx;padding: 40rpx;">
				<view style="text-align: center;font-size: 36rpx;font-weight: 600;margin-bottom: 30rpx;">
					修改错别字
				</view>
				<view style="margin-bottom: 20rpx;">
					<text style="color: #666;">原字：</text>
					<text style="color: #333;font-weight: bold;">{{ currentEditChar.zi }}</text>
				</view>
				<view style="margin-bottom: 30rpx;">
					<text style="color: #666;">正确字：</text>
				</view>
				<input type="text" class="inp" v-model="editCorrectText" placeholder="请输入正确的字" />
				<view class="f f-a-c f-j-c">
					<view @click="confirmEdit" class="confirm-btn f f-a-c f-j-c">
						确认修改
					</view>
					<view @click="cancelEdit" class="cancel-btn f f-a-c f-j-c">
						取消
					</view>
				</view>
			</view>
		</u-popup>
	</view>
</template>

<script>
	import {
		getErrorChars,
		getMissingChars,
		getCharCenter,
		isClickInChar
	} from "@/utils/correctUtils.js"

	export default {
		props: {
			imgurl: {
				type: String,
				required: true
			},
			list: {
				type: Array,
				required: true,
				default: () => []
			}
		},
		data() {
			return {
				canvasNode: null,
				ctx: null,
				dpr: 1,
				// 图片相关
				bgImgPath: '',
				originalImageWidth: 0,
				originalImageHeight: 0,
				canvasWidth: 0,
				canvasHeight: 0,
				canvasDisplayWidth: 0,
				canvasDisplayHeight: 0,
				// 样式配置
				circleSize: 25,
				lineWidth: 4,
				fontSize: 50,
				// 错别字数据
				errorChars: [],
				missingChars: [], // 新增：漏写字数据
				markedChars: [], // 已标记的字符
				// 交互相关
				touchStartX: 0,
				touchStartY: 0,
				isMoving: false,
				moveThreshold: 10,
				// 编辑相关
				showEditDialog: false,
				currentEditChar: {},
				editCorrectText: ''
			}
		},
		computed: {
			canvasStyle() {
				// 如果有原图尺寸，按比例计算显示尺寸
				if (this.canvasWidth && this.canvasHeight) {
					// 限制最大宽度为750rpx
					const maxWidth = 750
					const scale = Math.min(maxWidth / this.canvasWidth, 1)
					const displayWidth = this.canvasWidth * scale
					const displayHeight = this.canvasHeight * scale

					return `width: ${displayWidth}rpx; height: ${displayHeight}rpx; border: 1px solid #ccc;`
				} else {
					return 'width: 750rpx; height: 1000rpx; border: 1px solid #ccc;'
				}
			}
		},
		watch: {
			imgurl: {
				handler(newVal) {
					if (newVal) {
						this.loadImage()
					}
				},
				immediate: true
			},
			list: {
				handler(newVal) {
					if (newVal && newVal.length > 0) {
						console.log(this.list,'这是list');
						
						this.processCorrectData()
					}
				},
				immediate: true,
				deep: true
			}
		},
		mounted() {
			// 延迟执行，确保DOM完全准备好
			setTimeout(() => {
				this.initCanvas()
			}, 100)
		},
		methods: {
			/**
			 * 加载网络图片
			 */
			async loadImage() {
				if (!this.imgurl) {
					return
				}

				try {
					let imagePath = this.imgurl

					// 判断是否为网络图片
					if (this.imgurl.startsWith('http')) {
						// 检查网络状态
						const networkInfo = await this.getNetworkType()

						if (networkInfo.networkType === 'none') {
							throw new Error('网络连接不可用')
						}

						// 下载网络图片到本地
						const downloadRes = await this.downloadFile(this.imgurl)
						imagePath = downloadRes.tempFilePath
					}

					// 获取图片信息
					const imageInfo = await this.getImageInfo(imagePath)

					this.bgImgPath = imagePath
					this.originalImageWidth = imageInfo.width
					this.originalImageHeight = imageInfo.height

					// 直接使用原图尺寸作为Canvas尺寸
					this.canvasWidth = imageInfo.width
					this.canvasHeight = imageInfo.height

					// 根据图片大小设置样式参数
					if (this.canvasWidth > 2000) {
						this.lineWidth = 4
						this.circleSize = 60
						this.fontSize = 120
					} else {
						this.lineWidth = 2
						this.circleSize = 25
						this.fontSize = 50
					}

					// 如果canvas已经初始化，直接设置，否则等待初始化完成
					if (this.canvasNode && this.ctx) {
						this.setupCanvas()
					}
				} catch (error) {
					console.error('图片加载失败:', error)

					// 显示具体的错误信息
					let errorMessage = '图片加载失败'
					if (error.message && error.message.includes('downloadFile')) {
						errorMessage = '网络图片下载失败，请检查网络连接和域名配置'
					} else if (error.message && error.message.includes('getImageInfo')) {
						errorMessage = '图片信息获取失败，图片可能损坏'
					}

					uni.showToast({
						title: errorMessage,
						icon: 'none',
						duration: 3000
					})

					// 加载失败时绘制测试背景
					if (this.canvasNode && this.ctx) {
						this.drawTestBackground()
					}
				}
			},

			/**
			 * 获取网络状态
			 */
			getNetworkType() {
				return new Promise((resolve) => {
					uni.getNetworkType({
						success: resolve,
						fail: () => resolve({
							networkType: 'unknown'
						})
					})
				})
			},
			/**
			 * 下载文件
			 */
			downloadFile(url) {
				return new Promise((resolve, reject) => {
					uni.downloadFile({
						url: url,
						success: (res) => {
							if (res.statusCode === 200) {
								resolve(res)
							} else {
								reject(new Error(`下载失败，状态码: ${res.statusCode}`))
							}
						},
						fail: (error) => {
							reject(error)
						}
					})
				})
			},

			/**
			 * 获取图片信息
			 */
			getImageInfo(src) {
				return new Promise((resolve, reject) => {
					uni.getImageInfo({
						src: src,
						success: resolve,
						fail: reject
					})
				})
			},

			/**
			 * 初始化canvas
			 */
			initCanvas() {
				const query = wx.createSelectorQuery().in(this)
				query.select('#myCanvas')
					.fields({
						node: true,
						size: true
					})
					.exec(res => {
						if (res[0]) {
							this.canvasNode = res[0].node
							this.canvasDisplayWidth = res[0].width
							this.canvasDisplayHeight = res[0].height
							this.ctx = this.canvasNode.getContext('2d')
							this.dpr = uni.getSystemInfoSync().pixelRatio

							// 如果图片已经加载好，直接设置canvas
							if (this.bgImgPath) {
								this.setupCanvas()
							}
						}
					})
			},

			/**
			 * 设置canvas
			 */
			setupCanvas() {
				if (!this.canvasNode || !this.ctx) {
					return
				}

				// 设置canvas实际尺寸（考虑DPR）
				this.canvasNode.width = this.canvasWidth * this.dpr
				this.canvasNode.height = this.canvasHeight * this.dpr
				this.ctx.scale(this.dpr, this.dpr)

				if (this.bgImgPath) {
					// 有图片时加载图片
					const img = this.canvasNode.createImage()
					img.src = this.bgImgPath

					img.onload = () => {
						// 先清空Canvas
						this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)

						// 直接1:1绘制图片
						this.ctx.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight)

						// 绘制标记
						this.drawMarkers()
					}

					img.onerror = (error) => {
						// 图片加载失败时绘制测试背景
						this.drawTestBackground()
					}
				} else {
					// 没有图片时绘制测试背景
					this.drawTestBackground()
				}
			},

			/**
			 * 绘制测试背景（用于调试）
			 */
			drawTestBackground() {
				if (!this.ctx) {
					return
				}

				// 设置默认canvas尺寸如果还没有图片
				if (!this.canvasWidth || !this.canvasHeight) {
					this.canvasWidth = 750
					this.canvasHeight = 1000
				}

				// 设置canvas实际尺寸（考虑DPR）
				this.canvasNode.width = this.canvasWidth * this.dpr
				this.canvasNode.height = this.canvasHeight * this.dpr
				this.ctx.scale(this.dpr, this.dpr)

				// 绘制一个渐变背景用于测试
				const gradient = this.ctx.createLinearGradient(0, 0, this.canvasWidth, this.canvasHeight)
				gradient.addColorStop(0, '#f0f0f0')
				gradient.addColorStop(1, '#e0e0e0')

				this.ctx.fillStyle = gradient
				this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight)

				// 绘制一些测试文字
				this.ctx.fillStyle = '#333'
				this.ctx.font = '40px Arial'
				this.ctx.textAlign = 'left'
				this.ctx.textBaseline = 'top'
				this.ctx.fillText('Canvas测试', 50, 100)
				this.ctx.fillText('等待图片加载...', 50, 150)

				// 绘制标记
				this.drawMarkers()
			},

			/**
			 * 处理批改数据
			 */
			processCorrectData() {
				if (!this.list || this.list.length === 0) {
					return
				}

				this.errorChars = getErrorChars(this.list)
				this.missingChars = getMissingChars(this.list)

				// 重新构建markedChars，包含位置信息
				this.markedChars = []
				this.list.forEach((item, listIndex) => {
					if (item.chars && Array.isArray(item.chars)) {
						item.chars.forEach((char, charIndex) => {
							// type为0的错别字自动标注，或者是已手动标注且不是type=1的字符
							// 新增：type为-1且有wz的漏写字也要标注
							if (
								char.type === 0 ||
								(char.isMarked && char.type !== 1) ||
								(char.type === -1 && char.wz)
							) {
								this.markedChars.push({
									...char,
									listIndex,
									charIndex
								})
							}
						})
					}
				})

				// 如果canvas已准备好，重新绘制
				if (this.ctx && this.bgImgPath) {
					this.redraw()
				}
			},

			/**
			 * 绘制标记
			 */
			drawMarkers() {
				if (!this.ctx) return

				// 检查是否全部正确（errorZis字段为空）
				this.checkAndDrawCorrectMark()

				// 绘制错别字标记
				this.drawErrorMarkers()
			},

			/**
			 * 检查并绘制全对标记
			 */
			checkAndDrawCorrectMark() {
				// 检查是否有错别字数据
				const hasErrorChars = this.errorChars && this.errorChars.length > 0
				const hasMarkedChars = this.markedChars && this.markedChars.length > 0

				// 如果没有错误字符且没有已标记的字符，说明全部正确
				if (!hasErrorChars && !hasMarkedChars) {
					this.drawCorrectCheckMark()
				}
			},

			/**
			 * 绘制全对标记
			 */
			drawCorrectCheckMark() {
				if (!this.ctx) return

				// 在居中位置绘制dui.png图片
				this.drawDuiImage()

				// 在右下角绘制赞的图片
				this.drawZanImage()
			},

			/**
			 * 绘制dui.png图片到居中位置
			 */
			drawDuiImage() {
				if (!this.ctx || !this.canvasNode) return

				const img = this.canvasNode.createImage()
				img.src = '/static/dui.png'

				img.onload = () => {
					// 设置图片大小和位置
					const imgSize = Math.min(this.canvasWidth, this.canvasHeight) * 0.5 // 图片大小调大一些
					const centerX = this.canvasWidth * 0.5 // 居中X坐标
					const centerY = this.canvasHeight * 0.8 // 居中Y坐标
					const imgX = centerX - imgSize / 2 // 图片左上角X坐标
					const imgY = centerY - imgSize / 2 // 图片左上角Y坐标

					// 绘制图片到居中位置
					this.ctx.drawImage(img, imgX, imgY, imgSize, imgSize)
				}

				img.onerror = (error) => {
					// 如果图片加载失败，在居中位置绘制文字替代
					this.ctx.fillStyle = '#ff0000'
					this.ctx.font = `bold ${Math.round(this.fontSize * 1.5)}px Arial`
					this.ctx.textAlign = 'center'
					this.ctx.textBaseline = 'middle'

					// 在居中位置显示"全对"文字
					const centerX = this.canvasWidth * 0.5
					const centerY = this.canvasHeight * 0.5
					this.ctx.fillText('全对', centerX, centerY)
				}
			},

			/**
			 * 绘制赞的图片到右下角
			 */
			drawZanImage() {
				if (!this.ctx || !this.canvasNode) return

				const img = this.canvasNode.createImage()
				img.src = '/static/zan.png'

				img.onload = () => {
					// 设置图片大小和位置
					const imgSize = Math.min(this.canvasWidth, this.canvasHeight) * 0.12 // 图片大小稍微调小一点
					const padding = 10 // 距离边缘的距离
					const imgX = this.canvasWidth - imgSize - padding // 右下角X坐标
					const imgY = this.canvasHeight - imgSize - padding // 右下角Y坐标

					// 绘制图片到右下角
					this.ctx.drawImage(img, imgX, imgY, imgSize, imgSize)
				}

				img.onerror = (error) => {
					// 如果图片加载失败，在右下角绘制一个文字替代
					this.ctx.fillStyle = '#ff6600'
					this.ctx.font = `bold ${Math.round(this.fontSize * 0.6)}px Arial`
					this.ctx.textAlign = 'right'
					this.ctx.textBaseline = 'bottom'

					// 确保文字也在右下角
					const textX = this.canvasWidth - 20
					const textY = this.canvasHeight - 20
					this.ctx.fillText('👍', textX, textY)
				}
			},

			/**
			 * 绘制错别字标记
			 */
			drawErrorMarkers() {
				if (!this.markedChars || this.markedChars.length === 0) {
					return
				}

				this.ctx.strokeStyle = '#ff0000'
				this.ctx.fillStyle = '#ff0000'
				this.ctx.lineWidth = Math.max(1, this.lineWidth + 1)
				this.ctx.font = `bold ${Math.round(this.fontSize * 1.2)}px Arial`

				this.markedChars.forEach((char, index) => {
					// 直接使用原图坐标系的中心点
					const originalCenter = getCharCenter(char.wz)

					// 使用稍大的圈圈半径，确保更明显
					const enlargedRadius = this.circleSize + 25

					// 绘制红色圆圈（直接使用原图坐标）
					this.ctx.beginPath()
					this.ctx.arc(originalCenter.x, originalCenter.y, enlargedRadius, 0, Math.PI * 2)
					this.ctx.stroke()
				})
			},

			/**
			 * 处理触摸开始
			 */
			handleTouchStart(e) {
				const touch = e.touches[0]
				const canvasCoord = this.convertDisplayToCanvas(touch.x, touch.y)

				this.touchStartX = canvasCoord.x
				this.touchStartY = canvasCoord.y
				this.isMoving = false
			},

			/**
			 * 处理触摸移动
			 */
			handleTouchMove(e) {
				const touch = e.touches[0]
				const canvasCoord = this.convertDisplayToCanvas(touch.x, touch.y)

				const dx = Math.abs(canvasCoord.x - this.touchStartX)
				const dy = Math.abs(canvasCoord.y - this.touchStartY)

				if (dx > this.moveThreshold || dy > this.moveThreshold) {
					this.isMoving = true
				}
			},

			/**
			 * 处理触摸结束
			 */
			handleTouchEnd(e) {
				if (!this.isMoving) {
					// 这是一次点击
					this.handleClick(this.touchStartX, this.touchStartY)
				}
			},

			/**
			 * 处理点击事件
			 */
			handleClick(x, y) {
				// 遍历所有list中的字符，检测是否点击了带有wz信息的字符
				for (let listIndex = 0; listIndex < this.list.length; listIndex++) {
					const item = this.list[listIndex]
					if (!item.chars || !Array.isArray(item.chars)) continue

					for (let charIndex = 0; charIndex < item.chars.length; charIndex++) {
						const char = item.chars[charIndex]

						// 只检测带有wz信息的字符
						if (!char.wz || char.wz.l === undefined || char.wz.t === undefined || char.wz.w === undefined ||
							char.wz.h === undefined) {
							continue
						}

						// 增大点击检测范围，使用更大的padding
						const padding = Math.max(this.circleSize, 30) // 至少30像素的点击范围
						if (isClickInChar(x, y, char.wz, padding)) {
							// 检查这个字符是否已经被标注
							const isMarked = this.isCharMarked(listIndex, charIndex)

							if (isMarked) {
								// 如果已经标注，则删除标注
								this.removeCharMark(listIndex, charIndex)
								uni.showToast({
									title: '已删除标注',
									icon: 'success'
								})
							} else {
								// 如果未标注，则弹出编辑弹窗
								this.showEditForChar(listIndex, charIndex)
							}
							return
						}
					}
				}
			},

			/**
			 * 检查字符是否已被标注
			 */
			isCharMarked(listIndex, charIndex) {
				const char = this.list[listIndex].chars[charIndex]
				// type为0的错别字自动视为已标注，或者是手动标注的字符
				// type为1的字符（正确字符）不被视为已标注
				return char.type === 0 || (char.isMarked === true && char.type !== 1)
			},

			/**
			 * 删除字符标注
			 */
			removeCharMark(listIndex, charIndex) {
				// 从原始list中删除标注信息
				const char = this.list[listIndex].chars[charIndex]

				// 删除标记：将type设置为1（正确），清除标注信息
				this.$set(char, 'type', 1) // 设置为正确字符
				this.$set(char, 'isMarked', false)

				// 从markedChars中移除
				this.markedChars = this.markedChars.filter(markedChar => {
					return !(markedChar.listIndex === listIndex && markedChar.charIndex === charIndex)
				})

				// 通过$emit将更新后的list同步到父组件
				const cleanedList = this.getCleanedList()
				this.$emit('updateList', cleanedList)

				// 重新绘制
				this.redraw()
			},

			/**
			 * 显示字符编辑弹窗
			 */
			showEditForChar(listIndex, charIndex) {
				const char = this.list[listIndex].chars[charIndex]

				this.showEditDialog = true
				this.currentEditChar = {
					...char,
					listIndex,
					charIndex
				}
				this.editCorrectText = char.origin || ''
			},

			/**
			 * 清理list数据，去掉isMarked参数
			 */
			getCleanedList() {
				const cleanedList = JSON.parse(JSON.stringify(this.list))
				cleanedList.forEach(item => {
					if (item.chars && Array.isArray(item.chars)) {
						item.chars.forEach(char => {
							delete char.isMarked
						})
					}
				})
				return cleanedList
			},

			/**
			 * 转换显示坐标到canvas坐标
			 */
			convertDisplayToCanvas(displayX, displayY) {
				if (!this.canvasDisplayWidth || !this.canvasDisplayHeight || !this.canvasWidth || !this.canvasHeight) {
					return {
						x: displayX,
						y: displayY
					}
				}

				const realX = displayX / this.canvasDisplayWidth * this.canvasWidth
				const realY = displayY / this.canvasDisplayHeight * this.canvasHeight

				return {
					x: realX,
					y: realY
				}
			},

			/**
			 * 确认编辑
			 */
			confirmEdit() {
				if (!this.editCorrectText.trim()) {
					uni.showToast({
						title: '请输入正确的字',
						icon: 'none'
					})
					return
				}

				const {
					listIndex,
					charIndex
				} = this.currentEditChar

				// 更新原始list数组中的数据
				const char = this.list[listIndex].chars[charIndex]
				// 用户编辑的字替换为origin字段
				this.$set(char, 'origin', this.editCorrectText.trim())
				this.$set(char, 'isMarked', true)
				// 手动纠错的字符设置type为0（错别字）
				this.$set(char, 'type', 0)

				// 检查是否已经在markedChars中，如果不在则添加
				const existingIndex = this.markedChars.findIndex(markedChar =>
					markedChar.listIndex === listIndex && markedChar.charIndex === charIndex
				)

				if (existingIndex === -1) {
					// 添加到markedChars中，包含位置信息
					this.markedChars.push({
						...char,
						listIndex,
						charIndex
					})
				} else {
					// 更新现有的markedChar
					this.markedChars[existingIndex] = {
						...char,
						listIndex,
						charIndex
					}
				}

				// 通过$emit将更新后的list同步到父组件
				const cleanedList = this.getCleanedList()
				this.$emit('updateList', cleanedList)

				// 重新绘制
				this.redraw()

				// 关闭弹出层
				this.cancelEdit()

				uni.showToast({
					title: '修改成功',
					icon: 'success'
				})
			},

			/**
			 * 取消编辑
			 */
			cancelEdit() {
				this.showEditDialog = false
				this.currentEditChar = {}
				this.editCorrectText = ''
			},

			/**
			 * 重新绘制
			 */
			redraw() {
				if (!this.ctx || !this.bgImgPath) return

				// 清除canvas
				this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)

				// 重新绘制背景图片
				const img = this.canvasNode.createImage()
				img.src = this.bgImgPath

				img.onload = () => {
					// 直接1:1绘制图片
					this.ctx.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight)

					// 重新绘制标记
					this.drawMarkers()
				}
			}
		},

		beforeDestroy() {
			// 清理资源
			if (this.canvasNode) {
				this.canvasNode = null
				this.ctx = null
			}
		}
	}
</script>

<style>
	.container {
		/* padding: 20rpx; */
	}

	.confirm-btn {
		width: 180rpx;
		height: 70rpx;
		background: #05C490;
		border-radius: 20rpx;
		font-size: 28rpx;
		color: #FFFFFF;
		margin-right: 20rpx;
	}

	.cancel-btn {
		width: 180rpx;
		height: 70rpx;
		background: #cccccc;
		border-radius: 20rpx;
		font-size: 28rpx;
		color: #666666;
	}

	.inp {
		border-radius: 20rpx;
		border: 2rpx solid #CCCCCC;
		color: #000;
		padding-left: 20rpx;
		height: 70rpx;
		width: 100%;
		margin-bottom: 30rpx;
	}

	.inp::placeholder {
		color: #CCCCCC;
	}

	.f {
		display: flex;
	}

	.f-a-c {
		align-items: center;
	}

	.f-j-c {
		justify-content: center;
	}
</style>